home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 6 / QRZ Ham Radio Callsign Database - Volume 6.iso / pc / files / dsp / dspkgctr.z / dspkgctr / gcc / config / out-dsp96k.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-08  |  14.7 KB  |  766 lines

  1. /* Subroutines for insn-output.c for Motorola dsp96000
  2.    Copyright ( C ) 1988 Free Software Foundation, Inc.
  3.  
  4.    $Id: out-dsp96k.c,v 1.23 91/07/31 17:25:28 pete Exp $
  5.  
  6. This file is part of GNU CC.
  7.  
  8. GNU CC is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY.  No author or distributor
  10. accepts responsibility to anyone for the consequences of using it
  11. or for whether it serves any particular purpose or works at all,
  12. unless he says so in writing.  Refer to the GNU CC General Public
  13. License for full details.
  14.  
  15. Everyone is granted permission to copy, modify and redistribute
  16. GNU CC, but only under the conditions described in the
  17. GNU CC General Public License.     A copy of this license is
  18. supposed to have been given to you along with GNU CC so you
  19. can know your rights and responsibilities.  It should be in a
  20. file named COPYING.  Among other things, the copyright notice
  21. and this notice must be preserved on all copies.  */
  22.  
  23.  
  24. static char Version[]
  25.     = "$Header: /usr1/dsp/cvsroot/source/gcc/config/out-dsp96k.c,v 1.23 91/07/31 17:25:28 pete Exp $";
  26.  
  27.  
  28. #ifndef FILE
  29. #include <stdio.h>
  30. #endif
  31. #include <ctype.h>
  32.  
  33. #include <string.h>
  34. /* #include <malloc.h> */
  35.  
  36. #include "flags.h"
  37. #include "tree.h"
  38.  
  39. #if defined ( _DOS_ )
  40. extern void *malloc( );
  41. #endif
  42.  
  43. extern FILE* asm_out_file;
  44. extern char call_used_regs[];
  45. extern char regs_ever_live[];
  46. extern int frame_pointer_needed;
  47.  
  48. # define LAST_DATA_REGISTER 23
  49. char LocalBusy[FIRST_PSEUDO_REGISTER];
  50. int FirstSave;
  51.  
  52. /* initialized here for the first function; reinitialized for each subsequent
  53.    function in toplev.c */
  54. func_attributes current_func_info = FUNC_NO_INFO;
  55.  
  56. char mem_space;
  57. char memory_model;
  58.  
  59. static char* RegNames[] = REGISTER_NAMES;
  60.  
  61. static char* SFregs[] =
  62. {
  63.     "d0.s", "????", "????", "d1.s", "????", "????",
  64.     "d2.s", "????", "????", "d3.s", "????", "????",
  65.     "d4.s", "????", "????", "d5.s", "????", "????",
  66.     "d6.s", "????", "????", "d7.s", "????", "????",
  67.  
  68.     "????", "????", "????", "????", "????", "????",
  69.     "????", "????", "????", "????", "????", "????",
  70.     "????", "????", "????", "????", "????", "????",
  71.     "????", "????", "????", "????", "????", "????",
  72.     "????", "????", "????", "????", "????", "????",
  73.     "????", "????", "????", "????", "????", "????",
  74.     "????", "????", "????", "????", "????", "????",
  75.     "????", "????", "????", "????", "????", "????",
  76. };
  77.  
  78.  
  79. static char* DFregs[] =
  80. {
  81.     "d0.d", "????", "????", "d1.d", "????", "????",
  82.     "d2.d", "????", "????", "d3.d", "????", "????",
  83.     "d4.d", "????", "????", "d5.d", "????", "????",
  84.     "d6.d", "????", "????", "d7.d", "????", "????",
  85.  
  86.     "????", "????", "????", "????", "????", "????",
  87.     "????", "????", "????", "????", "????", "????",
  88.     "????", "????", "????", "????", "????", "????",
  89.     "????", "????", "????", "????", "????", "????",
  90.     "????", "????", "????", "????", "????", "????",
  91.     "????", "????", "????", "????", "????", "????",
  92.     "????", "????", "????", "????", "????", "????",
  93.     "????", "????", "????", "????", "????", "????",
  94. };
  95.  
  96.  
  97. static char* SIregs[] =
  98. {
  99.     "d0.l", "d0.m", "d0.h", "d1.l", "d1.m", "d1.h",
  100.     "d2.l", "d2.m", "d2.h", "d3.l", "d3.m", "d3.h",
  101.     "d4.l", "d4.m", "d4.h", "d5.l", "d5.m", "d5.h",
  102.     "d6.l", "d6.m", "d6.h", "d7.l", "d7.m", "d7.h",
  103.     "r0",   "r1",   "r2",   "r3",   "r4",   "r5",  "r6", "r7",
  104.     "n0",   "n1",   "n2",   "n3",   "n4",   "n5",  "n6", "n7"
  105. };
  106.  
  107.  
  108. static char* 
  109. Rname ( Regno, Mode )
  110.     int Regno;
  111.     enum machine_mode Mode;
  112. {
  113.     switch ( Mode )
  114.     {
  115.     case SFmode:
  116.     return ( SFregs[Regno] );
  117.  
  118.     case DFmode:
  119.     return ( DFregs[Regno] );
  120.  
  121.     default:
  122.     return ( SIregs[Regno] );
  123.     }
  124. }
  125.  
  126. static void 
  127. SetLocalBusy ()
  128. {
  129.     int i;
  130.     int j;
  131.  
  132.     /* Store register usage ingo in LocalBusy. */
  133.     for ( i = 0; i < FIRST_PSEUDO_REGISTER; i++ )
  134.     {
  135.     LocalBusy[i]
  136.         = ( ( 0 != regs_ever_live[i] )
  137.            && ( 0 == call_used_regs[i] ) ) ? i : 0;
  138.     }
  139.     
  140.     /* Update LocalBusy to denote register pairs. */
  141.     for ( i = 0; i < LAST_DATA_REGISTER; i += 3 )
  142.     {
  143.     /* First look for .l/.m pairs */
  144.     if ( 0 != LocalBusy[i] && 0 != LocalBusy[i + 1] )
  145.     {
  146.         LocalBusy[i] = i + 1;
  147.         LocalBusy[i + 1] = 0;
  148.         continue;
  149.     }
  150.  
  151.     /* Next look for .l/.l pairs */
  152.     for ( j = i + 3; j < LAST_DATA_REGISTER; j += 3 )
  153.     {
  154.         if ( 0 != LocalBusy[i] && 0 != LocalBusy[j] )
  155.         {
  156.         LocalBusy[i] = j;
  157.         LocalBusy[j] = 0;
  158.         break;
  159.         }
  160.     }
  161.     }
  162.     
  163.     /* Get the index in LocalBusy of the first register or pair saved */
  164.     for ( FirstSave = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++ )
  165.     {
  166.     if ( 0 != LocalBusy[i] )
  167.     {
  168.         FirstSave = i;
  169.         break;
  170.     }
  171.     }
  172. }
  173.  
  174.  
  175. static void 
  176. PushRegs ( file )
  177.     FILE* file;
  178. {
  179.     int i;
  180.  
  181.     FirstSave = -1;
  182.     
  183.     if ( 'l' != memory_model )
  184.     {
  185.     for ( i = 0; i < FIRST_PSEUDO_REGISTER; ++ i )
  186.     {
  187.         if (( 0 != regs_ever_live[i] ) && ( 0 == call_used_regs[i] ))
  188.         {
  189.         if ( 0 > FirstSave )
  190.         {
  191.             FirstSave = i;
  192.         }
  193.         
  194.         fprintf ( file, "\tmove    %s,%c:(r6)+\n",
  195.              Rname ( i, SImode ), mem_space );
  196.         }
  197.     }
  198.     return;
  199.     }
  200.     
  201.     for ( i = 0; i < FIRST_PSEUDO_REGISTER; i++ )
  202.     {
  203.     if ( 0 == LocalBusy[i] )
  204.     {
  205.         continue;
  206.     }
  207.  
  208.     if ( i == LocalBusy[i] )
  209.     {
  210.         if ( 0 > FirstSave )
  211.         {
  212.         FirstSave = i;
  213.         }
  214.  
  215.         fprintf ( file, "\tmove\t%s,y:(r6)+\n", Rname ( i, SImode ) );
  216.         continue;
  217.     }
  218.  
  219.     /* .l/.m pair ? */
  220.     if ( ( i + 1 ) == LocalBusy[i] )
  221.     {
  222.         if ( 0 > FirstSave )
  223.         {
  224.         FirstSave = i;
  225.         }
  226.  
  227.         fprintf ( file, "\tmove\td%d.ml,l:(r6)+\n", i / 3 );
  228.         continue;
  229.     }
  230.     
  231.     /* .l/.l pair */
  232.     if ( 0 > FirstSave )
  233.     {
  234.         FirstSave = i;
  235.     }
  236.  
  237.     fprintf ( file, "\tmove\t%s,x:(r6)+ %s,y:\n",
  238.          Rname ( i, SImode ),
  239.          Rname ( LocalBusy[i], SImode ) );
  240.     }
  241. }
  242.  
  243.  
  244. static void 
  245. PopRegs ( file )
  246.     FILE* file;
  247. {
  248.     int i;
  249.     int first_save = 0;
  250.  
  251. #define SAVE_CHECK \
  252. {\
  253.     if ( ! first_save )\
  254.     {\
  255.     first_save = 1;\
  256.     fprintf ( file, "\tmove    (r6)-\n" );\
  257.     }\
  258. }
  259.     
  260.     if ( 'l' != memory_model )
  261.     {
  262.     for ( i = FIRST_PSEUDO_REGISTER - 1; 0 <= i; -- i )
  263.     {
  264.         if (( 0 != regs_ever_live[i] ) && ( 0 == call_used_regs[i] ))
  265.         {
  266.         SAVE_CHECK;
  267.  
  268.         if ( i == FirstSave )
  269.         {
  270.             fprintf ( file, "\tmove    %c:(r6),%s\n", mem_space,
  271.                  Rname ( i, SImode ));
  272.         }
  273.         else
  274.         {
  275.             fprintf ( file, "\tmove    %c:(r6)-,%s\n", mem_space,
  276.                  Rname ( i, SImode ));
  277.         }
  278.         }
  279.     }
  280.     return;
  281.     }
  282.     
  283.     for ( i = FIRST_PSEUDO_REGISTER - 1; i > 0; i-- )
  284.     {
  285.     if ( 0 == LocalBusy[i] )
  286.     {
  287.         continue;
  288.     }
  289.  
  290.     SAVE_CHECK;
  291.     if ( i == LocalBusy[i] )
  292.     {
  293.         /* The last pop cannot adjust the stack pointer. */
  294.         if ( i == FirstSave )
  295.         {
  296.         fprintf ( file, "\tmove\ty:(r6),%s\n", Rname ( i, SImode ) );
  297.         }
  298.         else
  299.         {
  300.         fprintf ( file, "\tmove\ty:(r6)-,%s\n", Rname ( i, SImode ) );
  301.         }
  302.  
  303.         continue;
  304.     }
  305.  
  306.     /* The last pop cannot adjust the stack pointer. */
  307.     if ( i == FirstSave )
  308.     {
  309.         /* .l/.m pair ? */
  310.         if ( ( i + 1 ) == LocalBusy[i] )
  311.         {
  312.         fprintf ( file, "\tmove\tl:(r6),d%d.ml\n", i / 3 );
  313.         continue;
  314.         }
  315.     
  316.         /* .l/.l pair */
  317.         fprintf ( file, "\tmove\tx:(r6),%s y:,%s\n",
  318.              Rname ( i, SImode ),
  319.              Rname ( LocalBusy[i], SImode ) );
  320.     }
  321.     else
  322.     {
  323.         /* .l/.m pair ? */
  324.         if ( ( i + 1 ) == LocalBusy[i] )
  325.         {
  326.         fprintf ( file, "\tmove\tl:(r6)-,d%d.ml\n", i / 3 );
  327.         continue;
  328.         }
  329.  
  330.         /* .l/.l pair */
  331.         fprintf ( file, "\tmove\tx:(r6)-,%s y:,%s\n",
  332.              Rname ( i, SImode ),
  333.              Rname ( LocalBusy[i], SImode ) );
  334.     }
  335.     }
  336. }
  337.  
  338. /*
  339.  * Replace an address of the form Frame-pointer + Constant with an
  340.  * address that uses the Stack-pointer and a computed offset.
  341.  */
  342. rtx 
  343. fix_frame_pointer_address ( Addr, Depth )
  344.     rtx Addr;
  345.     int Depth;
  346. {
  347.     int Offset;
  348.     int Regno;
  349.  
  350.     SetLocalBusy ();
  351.  
  352.     if ( PLUS != GET_CODE ( Addr )
  353.     || XEXP ( Addr, 0 ) != frame_pointer_rtx
  354.     || CONST_INT != GET_CODE ( XEXP ( Addr, 1 ) ) )
  355.     {
  356.     return ( Addr );
  357.     }
  358.     
  359.     Offset = INTVAL ( XEXP ( Addr, 1 ) );
  360.  
  361.     for ( Regno = 0; Regno < FIRST_PSEUDO_REGISTER; Regno++ )
  362.     {
  363.     if ( 0 != LocalBusy[Regno] )
  364.     {
  365.         --Offset;
  366.     }
  367.     }
  368.  
  369.     return ( plus_constant ( stack_pointer_rtx, Offset ) );
  370. }
  371.  
  372.  
  373. int 
  374. go_if_legitimate_address ( Mode, X, Strict )
  375.     int Mode;
  376.     rtx X;
  377.     int Strict;
  378. {
  379.     /* constant pointer */
  380.     if ( CONSTANT_ADDRESS_P ( X ) )
  381.     {
  382.     return ( 1 );
  383.     }
  384.  
  385.     /* register pointer */
  386.     if ( REG_P ( X ) )
  387.     {
  388.     if ( ! Strict )
  389.     {
  390.         return ( 1 );
  391.     }
  392.  
  393.     if ( REGNO_OK_FOR_BASE_P ( REGNO ( X ) ) )
  394.     {
  395.         return ( 1 );
  396.     }
  397.  
  398.     return ( 0 );
  399.     }
  400.  
  401.     switch ( GET_CODE ( X ) )
  402.     {
  403.  
  404.     case PRE_DEC:
  405.     case POST_DEC:
  406.     case POST_INC:
  407.     if ( REG_P ( XEXP ( X, 0 ) ) )
  408.     {
  409.         if ( !Strict )
  410.         {
  411.         return ( 1 );
  412.         }
  413.  
  414.         if ( REGNO_OK_FOR_BASE_P ( REGNO ( XEXP ( X, 0 ) ) ) )
  415.         {
  416.         return ( 1 );
  417.         }
  418.     }
  419.  
  420.     return ( 0 );
  421.  
  422.     case CONST_INT:
  423.      return ( 1 );
  424.  
  425.     case PLUS:
  426.     if ( REG_P ( XEXP ( X, 0 ) )
  427.          && ( CONSTANT_ADDRESS_P ( XEXP ( X, 1 ) ) ) )
  428.     {
  429.         if ( ! Strict )
  430.         {
  431.         return ( 1 );
  432.         }
  433.  
  434.         if ( REGNO_OK_FOR_BASE_P ( REGNO ( XEXP ( X, 0 ) ) ) )
  435.         {
  436.         /* register + constant int */
  437.         return ( 1 );
  438.         }
  439.  
  440.         return ( 0 );
  441.     }
  442.  
  443.     if ( REG_P ( XEXP ( X, 1 ) )
  444.         && ( CONSTANT_ADDRESS_P ( XEXP ( X, 0 ) ) ) )
  445.     {
  446.         if ( ! Strict )
  447.         {
  448.         return ( 1 );
  449.         }
  450.  
  451.         if ( REGNO_OK_FOR_BASE_P ( REGNO ( XEXP ( X, 1 ) ) ) )
  452.         {
  453.         /* register + constant int */
  454.         return ( 1 );
  455.         }
  456.  
  457.         return ( 0 );
  458.     }
  459.  
  460.     default:
  461.     return ( 0 );
  462.     }
  463. }
  464.  
  465. void 
  466. print_operand ( file, X, Code )
  467.     FILE* file;
  468.     rtx X;
  469.     char Code;
  470. {
  471.     if ( 'n' == Code )
  472.     {
  473.     fprintf ( file, "\n" );
  474.     return;
  475.     }
  476.     
  477.     switch ( GET_CODE ( X ) )
  478.     {
  479.     
  480.     case REG:
  481.     /*
  482.      * Registers need special handling on m96k. When they are targets
  483.      * of moves, data alu registers must be suffiexed by .l,.m,.h,.s
  484.      * or .d Operands that may need this extension use the Code 'z'.
  485.      */
  486.     if ( 'z' == Code )
  487.     {
  488.         fprintf ( file, "%s", Rname ( REGNO ( X ), GET_MODE ( X ) ) );
  489.         return;
  490.     }
  491.  
  492.     fprintf ( file, "%s", RegNames [REGNO ( X )] );
  493.     return;
  494.  
  495.     case MEM:
  496.     output_address ( XEXP ( X, 0 ) );
  497.     return;
  498.  
  499.     case LABEL_REF:
  500.     case SYMBOL_REF:
  501.     fprintf ( file, "#" );
  502.     output_addr_const ( file, X );
  503.     return;
  504.  
  505.     case CONST_INT:
  506.     fprintf ( file, "#%d", INTVAL ( X ) );
  507.     return;
  508.  
  509.     case CONST_DOUBLE:
  510.     if ( GET_MODE ( X ) == SFmode )
  511.     {
  512.         union { double d; int i[2]; } u;
  513.         union { float f; int i; } u1;
  514.         u.i[0] = CONST_DOUBLE_LOW ( X );
  515.         u.i[1] = CONST_DOUBLE_HIGH ( X );
  516.         u1.f = u.d;
  517.  
  518.         if ( Code == 'f' )
  519.         {
  520.         fprintf ( file, "%.9g", u1.f );
  521.         return;
  522.         }
  523.  
  524.         fprintf ( file, "#$%x", u1.i );
  525.         return;
  526.     }
  527.  
  528.     if ( GET_MODE ( X ) != DImode )
  529.     {
  530.         union { double d; int i[2]; } u;
  531.         u.i[0] = CONST_DOUBLE_LOW ( X );
  532.         u.i[1] = CONST_DOUBLE_HIGH ( X );
  533.  
  534.         fprintf ( file, "%.20g", u.d );
  535.         return;
  536.     }
  537.  
  538.     default:
  539.     fprintf ( file, "#" );
  540.     output_addr_const ( file, X );
  541.     }
  542. }
  543.  
  544.  
  545. print_operand_address ( file, Addr )
  546.     FILE* file;
  547.     rtx Addr;
  548. {
  549.     register rtx Reg0;
  550.     register rtx Reg1;
  551.  
  552.     switch ( GET_CODE ( Addr ) )
  553.     {
  554.  
  555.     case REG:
  556.     fprintf ( file, "(%s)", RegNames [REGNO ( Addr )] );
  557.     break;
  558.  
  559.     case POST_INC:
  560.     fprintf ( file, "(%s)+", RegNames [REGNO ( XEXP ( Addr, 0 ) )] );
  561.     break;
  562.  
  563.     case POST_DEC:
  564.     fprintf ( file, "(%s)-", RegNames [REGNO ( XEXP ( Addr, 0 ) )] );
  565.     break;
  566.  
  567.     case PRE_DEC:
  568.     fprintf ( file, "-(%s)", RegNames [REGNO ( XEXP ( Addr, 0 ) )] );
  569.     break;
  570.  
  571.     case PLUS:
  572.     Reg0 = XEXP ( Addr, 0 );
  573.     Reg1 = XEXP ( Addr, 1 );
  574.  
  575.     if ( CONSTANT_ADDRESS_P ( Reg0 ))
  576.     {
  577.         fprintf ( file, "(" );
  578.         print_operand ( file, Reg1, 'c' );
  579.         fprintf ( file, "+" );
  580.         output_addr_const ( file, Reg0 );
  581.         fprintf ( file, ")" );
  582.         return;
  583.     }
  584.  
  585.     if ( CONSTANT_ADDRESS_P ( Reg1 ))
  586.     {
  587.         fprintf ( file, "(" );
  588.         print_operand ( file, Reg0, 'c' );
  589.         fprintf ( file, "+" );
  590.         output_addr_const ( file, Reg1 );
  591.         fprintf ( file, ")" );
  592.         return;
  593.     }
  594.  
  595.     fatal ( "unknown PLUS case in PRINT_OPERAND_ADDRESS" );
  596.     return;
  597.  
  598.     default:
  599.     output_addr_const ( file, Addr );
  600.     }
  601. }
  602.  
  603.  
  604. asm_output_opcode ( file, Opcode )
  605.     FILE* file;
  606.     char* Opcode;
  607. {
  608. }
  609.  
  610. void 
  611. notice_update_cc ( Exp, Insn )
  612.     rtx Exp;
  613.     rtx Insn;
  614. {
  615.     if ( SET == GET_CODE ( Exp ) )
  616.     {
  617.     switch ( GET_CODE ( SET_DEST ( Exp ) ) )
  618.     {
  619.  
  620.     case CC0:
  621.         cc_status.flags = 0;
  622.         cc_status.value1 = SET_DEST ( Exp );
  623.         cc_status.value2 = SET_SRC ( Exp );
  624.         break;
  625.         
  626.     case REG:
  627.         switch ( GET_CODE ( SET_SRC ( Exp ) ) )
  628.         {
  629.         case CALL:
  630.         if ( SImode == GET_MODE ( SET_DEST ( Exp )))
  631.         {
  632.             cc_status.flags = 0;
  633.             cc_status.value1 = SET_DEST ( Exp );
  634.             cc_status.value2 = SET_SRC ( Exp );
  635.         }
  636.         else
  637.         {
  638.             CC_STATUS_INIT;
  639.         }
  640.         break;
  641.         
  642.         case MEM:
  643.         case REG:
  644.         case EQ:
  645.         case NE:
  646.         case GT:
  647.         case GTU:
  648.         case GE:
  649.         case GEU:
  650.         case LT:
  651.         case LTU:
  652.         case LE:
  653.         case LEU:
  654.         CC_STATUS_INIT;
  655.         break;
  656.  
  657.         default:
  658.         CC_STATUS_INIT;
  659.         break;
  660.         }
  661.         
  662.         break;
  663.  
  664.     case MEM:
  665.         CC_STATUS_INIT;
  666.         break;
  667.     }
  668.     }
  669. }
  670.  
  671. /* right now, we only handle the following types of mem expressions:
  672.    ( MEM ( PLUS REG CA ))
  673.    ( MEM ( CA ))
  674.    where CA is CONSTANT_ADDRESS_P */
  675.  
  676. static rtx
  677. gen_mem_plus_const_int_from_mem ( mem, const_int )
  678.     rtx mem;
  679.     int const_int;
  680. {
  681.     rtx addr = XEXP ( mem, 0 );
  682.     
  683.     switch ( GET_CODE ( addr ))
  684.     {
  685.     case PLUS:
  686.     if (( REG == GET_CODE ( XEXP ( addr, 0 ))) &&
  687.         ( CONSTANT_ADDRESS_P ( XEXP ( addr, 1 ))))
  688.     {
  689.         return gen_rtx ( MEM, GET_MODE ( mem ),
  690.                 gen_rtx ( PLUS, Pmode,
  691.                      XEXP ( addr, 0 ),
  692.                      gen_rtx ( CONST, Pmode,
  693.                           gen_rtx ( PLUS, Pmode,
  694.                                XEXP ( addr, 1 ),
  695.                    gen_rtx ( CONST_INT, VOIDmode, const_int )))));
  696.     }
  697.     else if (( REG == GET_CODE ( XEXP ( addr, 1 ))) &&
  698.          ( CONSTANT_ADDRESS_P ( XEXP ( addr, 0 ))))
  699.     {
  700.         return gen_rtx ( MEM, GET_MODE ( mem ),
  701.                 gen_rtx ( PLUS, Pmode,
  702.                      XEXP ( addr, 1 ),
  703.                      gen_rtx ( CONST, Pmode,
  704.                           gen_rtx ( PLUS, Pmode,
  705.                                XEXP ( addr, 0 ),
  706.                    gen_rtx ( CONST_INT, VOIDmode, const_int )))));
  707.     }
  708.     else
  709.     {
  710.         abort ( );
  711.     }
  712.     
  713.     default:
  714.     if ( CONSTANT_ADDRESS_P ( addr ))
  715.     {
  716.         return gen_rtx ( MEM, GET_MODE ( mem ),
  717.                 gen_rtx ( CONST, Pmode,
  718.                      gen_rtx ( PLUS, Pmode, addr,
  719.                           gen_rtx ( CONST_INT, VOIDmode,
  720.                                const_int ))));
  721.     }
  722.     abort ( );
  723.     }
  724.     abort ( );
  725. }
  726.  
  727. int
  728. local_first_parm_offset ( fundecl )
  729.     tree fundecl;
  730. {
  731.     return -2;
  732. }
  733.  
  734. int
  735. is_in_reg_p ( operand )
  736.     rtx operand;
  737. {
  738.     while ( SUBREG == GET_CODE ( operand ))
  739.     {
  740.     operand = XEXP ( operand, 0 );
  741.     }
  742.     
  743.     return ( REG == GET_CODE ( operand ));
  744. }
  745.  
  746. /* this extraneous function is needed because the MetaWare C compiler
  747.    can't handle the comma operator with pointer values. */
  748.  
  749. rtx
  750. local_function_incoming_arg ( cum, mode, type, named )
  751.     CUMULATIVE_ARGS cum;
  752.     enum machine_mode mode;
  753.     tree type;
  754.     int named;
  755. {
  756.     if ( 2 <= cum || BLKmode == mode || 0 == named )
  757.     {
  758.     current_func_info |= FUNC_HAS_STACK_PARMS;
  759.     return NULL;
  760.     }
  761.     return gen_rtx ( REG, ( mode ), 3 * cum );
  762. }
  763.  
  764. #include "dsp.c"
  765.  
  766.